<!--
 * @description: 仿真控制推演界面
 * @fileName: index.vue
 * @author: ssr
 * @date: 2022-08-16 11:16:49
 * @version: V1.0.0
!-->
<template>
  <div class="sub-container2">
    <SimHeader />
    <div class="sub-main">
      <CesiumMap v-model:custom-viewer="state.customViewerTuiyan" @viewer-ready="handleViewerReady" />
      <DeductControl v-show="panelStore.controlPanelShowTuiyan" @play="startPlayback" @pause="pausePlayback"
        @restart="restartSimulation" @speedChange="adjustPlaySpeed" @perspectiveChange="handlePerspectiveChange"
        @change="handlePerspectiveChange" />
      <DeductTime />
      <EntityList :class="panelStore.entityPanelShowTuiyan ? 'expand' : 'collapse'" />
      <EntityLog :class="panelStore.logPanelShowTuiyan ? 'expand' : 'collapse'" />
      <SystemInfo />
    </div>
  </div>
</template>
<script lang="ts" setup>
import {
  watch,
  reactive,
  toRefs,
  onMounted,
  onBeforeUnmount,
  defineOptions,
  onActivated,
  nextTick,
  computed
} from "vue";
import { createRoutesManagerTuiyan } from "@@/utils/RoutesManagerTuiyan";
import * as Cesium from "cesium";
import {
  CesiumMap,
  DeductControl,
  DeductTime,
  EntityList,
  EntityLog,
  SystemInfo,
} from "./components";
import SimHeader from "./components/header.vue";
import { getSituationData } from "@@/apis/situation";
import { useRoute } from "vue-router";
import {
  rmqStateTuiyan,
  simulPanelStateTuiyan,
  cesiumStateTuiyan,
  appStateTuiyan,
} from "@@/store-tuiyan/modules/index";
import { simulationStateTuiyan } from "@@/store-tuiyan/modules/simulation";
import { customStomp } from "@@/utils/CustomStomp.ts";
import { EntityGroupId, ControlMessageType } from "@@/enums/observation.ts";
import { createDomainManagerTuiyan } from "@@/utils/DomainManagerTuiyan";
import { Cartesian3 } from "cesium";
// 命名，方便keepAlive识别
defineOptions({
  name: "situationTuiyan",
});
// 定义类型
interface customViewerTuiyan {
  animationManager?: {
    getAnimationGroup: (id: string) => {
      datasource: {
        show: boolean;
        entities: {
          getById: (id: string) => any;
        }
      }
    }
  };
  scene?: any;
}

interface ISideStep {
  game_id?: string;
  simul_time?: number;
  obj_list?: any[];
}
// Props定义
const props = defineProps({
  selectValue: {
    type: Number,
    required: true,
    default: 1
  },
  taskStatus: {
    type: Number,
    required: true,
    default: 1
  }
});

const route = useRoute();
// 状态和Store
let rmqTimer: NodeJS.Timeout | undefined;
const store = cesiumStateTuiyan();
const simulStoreTuiyan = simulationStateTuiyan();
const panelStore = simulPanelStateTuiyan();

// 定义响应式状态
const state = reactive({
  customViewerTuiyan: null as customViewerTuiyan | null,
  progressPercentage: 0,
  currentStepIndex: 0,
  totalSteps: 100, // 假设总步骤数为100，可根据后端数据调整
  isPlaying: false,
  playSpeed: 1, // 播放速度倍率
});

// 切换播放状态
const togglePlayState = () => {
  state.isPlaying = !state.isPlaying;
  if (state.isPlaying) {
    startPlayback();
  } else {
    pausePlayback();
  }
};

// 切换播放/暂停
const togglePlay = () => {
  state.isPlaying = !state.isPlaying;
  if (state.isPlaying) {
    startPlayback();
  } else {
    pausePlayback();
  }
};

// 开始播放
const startPlayback = () => {
  // 防止多次调用
  if (rmqTimer) {
    clearInterval(rmqTimer);
  }

  // 重置位置逻辑
  if (state.currentStepIndex >= state.totalSteps - 1) {
    state.currentStepIndex = 0;
    updateProgress();
    applyStepData(state.currentStepIndex);
  }

  state.isPlaying = true;
  simulStoreTuiyan.setIsPause(false);

  rmqTimer = setInterval(() => {
    if (state.currentStepIndex < state.totalSteps - 1) {
      state.currentStepIndex++;
      updateProgress();
      applyStepData(state.currentStepIndex);
    } else {
      pausePlayback();
    }
  }, 1000 / state.playSpeed);
};

// 暂停播放
const pausePlayback = () => {
  if (rmqTimer) {
    clearInterval(rmqTimer);
    rmqTimer = undefined;
  }
  simulStoreTuiyan.setIsPause(true);
  state.isPlaying = false;
};

// 下一步
const nextStep = () => {
  if (state.currentStepIndex < state.totalSteps) {
    state.currentStepIndex++;
    updateProgress();
    applyStepData(state.currentStepIndex);
  }
};

// 上一步
const previousStep = () => {
  if (state.currentStepIndex > 0) {
    state.currentStepIndex--;
    updateProgress();
    applyStepData(state.currentStepIndex);
  }
};

// 更新进度
const updateProgress = () => {
  state.progressPercentage = Math.floor((state.currentStepIndex / state.totalSteps) * 100);
};

// 应用步骤数据
const applyStepData = async (stepIndex: number) => {

  if (stepIndex < 0 || stepIndex >= simulStoreTuiyan.steps.length) {
    return;
  }

  // 获取当前步骤数据
  let stepData = simulStoreTuiyan.applyStepData(stepIndex);

  if (!stepData) {
    return;
  }

  // 使用处理观察数据的新方法
  await simulStoreTuiyan.processObservationData(stepIndex);

  // 处理实体数据
  processEntityData(stepData);

  // 更新3D视图
  updateVisualization(stepData);
};

// 获取当前视角的步骤数据
const getStepDataForCurrentPerspective = (stepIndex: number) => {

  let stepData;
  if (simulStoreTuiyan.currentPerspective === 'red') {
    if (simulStoreTuiyan.redSteps && simulStoreTuiyan.redSteps.length > stepIndex) {
      stepData = simulStoreTuiyan.redSteps[stepIndex];
    }
  } else if (simulStoreTuiyan.currentPerspective === 'blue') {
    if (simulStoreTuiyan.blueSteps && simulStoreTuiyan.blueSteps.length > stepIndex) {
      stepData = simulStoreTuiyan.blueSteps[stepIndex];
    }
  } else {
    if (simulStoreTuiyan.steps && simulStoreTuiyan.steps.length > stepIndex) {
      stepData = simulStoreTuiyan.steps[stepIndex];
    }
  }

  if (!stepData) {
    // 如果没有对应视角的数据，回退到全局数据
    stepData = simulStoreTuiyan.steps[stepIndex];
  }

  return stepData;
};

// 更新仿真时间
const updateSimulationTime = (simulTime: number) => {
  if (simulTime) {
    const timeStr = new Date(simulTime * 1000).toISOString().substr(11, 8);
    simulStoreTuiyan.setSimulTime(timeStr);
  }
};

// 处理实体数据
const processEntityData = (stepData: ISideStep) => {
  if (!stepData.obj_list) return;
  // 更新实体位置
  if (state.customViewerTuiyan) {
    updateEntityPositions(state.customViewerTuiyan, stepData);
  }

  // 更新路径显示 - 修改条件确保始终尝试更新轨迹
  if (simulStoreTuiyan.routesManager) {
    // 确保路径显示标志为真
    if (!simulStoreTuiyan.isShowPath) {
      simulStoreTuiyan.isShowPath = true;
    }
    updateRoutes(simulStoreTuiyan.routesManager, stepData);
  } else {
  }

  // 更新日志信息
  updateLogs(stepData);
};

// 更新可视化
const updateVisualization = (stepData: ISideStep) => {
  // 请求重新渲染
  if (state.customViewerTuiyan?.scene) {
    try {
      state.customViewerTuiyan.scene.requestRender();
    } catch (e) {
    }
  }
};

// 更新实体位置
const updateEntityPositions = (customViewerTuiyan: customViewerTuiyan, step: ISideStep) => {
  if (!step.obj_list) return;
  // 获取动画管理器的实体组
  const groupAll = customViewerTuiyan.animationManager?.getAnimationGroup(EntityGroupId.all),
    groupRed = customViewerTuiyan.animationManager?.getAnimationGroup(EntityGroupId.red),
    groupBlue = customViewerTuiyan.animationManager?.getAnimationGroup(EntityGroupId.blue);
  // 遍历实体列表，更新位置
  step.obj_list && step.obj_list.forEach((entity: any) => {
    // 对于1.json数据需要转换字段
    const entity_id = entity.m_id?.toString() || entity.entity_id;
    const alliance = entity.m_Side === 1 ? "Red" : (entity.alliance || "Blue");
    let position;

    // 检查位置数据的格式并处理
    if (entity.m_Position) {
      // 从1.json数据中提取位置
      position = `${entity.m_Position.longitude},${entity.m_Position.latitude},${entity.m_Position.height || 0}`;
    } else {
      position = entity.position;
    }

    if (position) {
      const pos = position.split(","); // 经度,纬度,高度
      if (pos && pos.length === 3) {
        // 使用Cesium的Cartesian3.fromDegrees将经纬度转换为笛卡尔坐标
        const cartesian = Cesium.Cartesian3.fromDegrees(
          Number(pos[0]),
          Number(pos[1]),
          Number(pos[2])
        );

        // 根据alliance更新对应阵营的实体
        let targetEntity;
        if (alliance === "Blue") {
          targetEntity = groupBlue?.datasource.entities.getById(entity_id);
        } else {
          targetEntity = groupRed?.datasource.entities.getById(entity_id);
        }

        // 如果实体不存在，则创建
        if (!targetEntity) {
          // 创建实体
          const entityGroup = alliance === "Blue" ? groupBlue : groupRed;
          if (entityGroup) {
            entityGroup.datasource.entities.add({
              id: entity_id,
              name: entity.m_EntityName || entity.entity_name,
              position: cartesian,
              point: {
                pixelSize: 10,
                color: alliance === "Blue" ? Cesium.Color.BLUE : Cesium.Color.RED
              }
            });
          }
        } else {
          // 更新实体位置
          if (targetEntity.position) {
            targetEntity.position.setValue(cartesian);
          }
        }
      }
    }
  });
};

// 更新轨迹
const updateRoutes = (routesManager: any, step: ISideStep) => {
  if (!step.obj_list) return;
  if (!routesManager) return;
  if (!routesManager.entityRoutes) routesManager.entityRoutes = {};

  // 确保entityRoutes中没有对象值
  cleanAllEntityRoutes(routesManager);

  step.obj_list && step.obj_list.forEach((entity: any) => {
    const entity_id = entity.m_id?.toString() || entity.entity_id;
    let position;

    // 检查位置数据的格式并处理
    if (entity.m_Position) {
      position = `${entity.m_Position.longitude},${entity.m_Position.latitude},${entity.m_Position.height || 0}`;
    } else {
      position = entity.position;
    }

    if (position) {
      const pos = position.split(","); // 经度,纬度,高度
      if (pos && pos.length === 3) {
        try {
          // 确保所有坐标都是数字
          const longitude = Number(pos[0]);
          const latitude = Number(pos[1]);
          const height = Number(pos[2]);

          // 验证转换是否成功且数值有效
          if (isNaN(longitude) || isNaN(latitude) || isNaN(height)) {
            return;
          }

          const cartesian = Cesium.Cartesian3.fromDegrees(longitude, latitude, height);

          // 确保路径数组存在且仅包含数字
          if (!routesManager.entityRoutes[entity_id]) {
            routesManager.entityRoutes[entity_id] = [];
          } else {
            // 如果已存在，确保数组中只有数字
            const cleanedArray = [];
            for (let i = 0; i < routesManager.entityRoutes[entity_id].length; i++) {
              if (typeof routesManager.entityRoutes[entity_id][i] === 'number') {
                cleanedArray.push(routesManager.entityRoutes[entity_id][i]);
              }
            }
            routesManager.entityRoutes[entity_id] = cleanedArray;
          }

          // 直接添加经纬度(一定是数字类型)
          routesManager.entityRoutes[entity_id].push(longitude, latitude);
        } catch (error) {
          console.error("处理实体位置错误:", error, position);
        }
      }
    }
  });

  // 清理和刷新路径
  refreshAllEntityRoutes(routesManager);
};

// 清理所有路径数据，确保只有数字
const cleanAllEntityRoutes = (routesManager: any) => {
  if (!routesManager || !routesManager.entityRoutes) return;

  const cleanedRoutes = {};

  for (const entityId in routesManager.entityRoutes) {
    const routes = routesManager.entityRoutes[entityId];
    if (!Array.isArray(routes)) {
      cleanedRoutes[entityId] = [];
      continue;
    }

    // 过滤出所有数字类型的值
    const validNumbers = [];
    for (let i = 0; i < routes.length; i++) {
      if (typeof routes[i] === 'number' && !isNaN(routes[i])) {
        validNumbers.push(routes[i]);
      } else if (typeof routes[i] === 'object' && routes[i] !== null) {
        // 尝试从对象转换为经纬度
        try {
          // 尝试从对象创建Cartesian3
          const cartesian = new Cesium.Cartesian3(
            routes[i].x || 0,
            routes[i].y || 0,
            routes[i].z || 0
          );
          // 转换为经纬度
          const cartographic = Cesium.Cartographic.fromCartesian(cartesian);
          const longitude = Cesium.Math.toDegrees(cartographic.longitude);
          const latitude = Cesium.Math.toDegrees(cartographic.latitude);

          // 验证转换是否成功且有效
          if (!isNaN(longitude) && !isNaN(latitude)) {
            validNumbers.push(longitude, latitude);
          }
        } catch (e) {
          // 忽略无法转换的对象
          console.warn("无法转换的路径点对象", routes[i]);
        }
      } else if (typeof routes[i] === 'string') {
        // 尝试将字符串转换为数字
        const num = Number(routes[i]);
        if (!isNaN(num)) {
          validNumbers.push(num);
        }
      }
    }

    // 确保长度是偶数(有效的经纬度对)
    if (validNumbers.length % 2 !== 0) {
      validNumbers.pop();
    }

    cleanedRoutes[entityId] = validNumbers;
  }

  // 用清理后的数据替换原数据
  routesManager.entityRoutes = cleanedRoutes;
};

// 刷新所有路径
const refreshAllEntityRoutes = (routesManager: any) => {
  if (!routesManager || !routesManager.datasource) return;

  try {
    // 清除现有实体
    routesManager.datasource.entities.removeAll();

    // 确保先清理所有路径数据
    cleanAllEntityRoutes(routesManager);

    // 绘制所有有效路径
    for (const entityId in routesManager.entityRoutes) {
      const routes = routesManager.entityRoutes[entityId];

      // 至少需要2个点(4个坐标值)
      if (routes.length >= 4) {
        try {
          // 确保所有值都是数字
          for (let i = 0; i < routes.length; i++) {
            if (typeof routes[i] !== 'number' || isNaN(routes[i])) {
              return; // 如果任何一个不是数字，跳出当前路径
            }
          }

          // 创建实体路径
          const entity = new Cesium.Entity({
            id: entityId,
            polyline: {
              positions: Cesium.Cartesian3.fromDegreesArray(routes),
              width: 1,
              material: new Cesium.PolylineDashMaterialProperty({
                color: Cesium.Color.fromCssColorString("rgba(53, 181, 255, 1)")
              })
            }
          });

          routesManager.datasource.entities.add(entity);
        } catch (error) {
          // 如果创建失败，移除可能出问题的路径
          delete routesManager.entityRoutes[entityId];
        }
      }
    }
  } catch (error) {
    console.error("刷新路径失败:", error);
  }
};

// 更新日志
const updateLogs = (step: ISideStep) => {
  if (!step.obj_list) return;

  const redLogList: any[] = [];
  const blueLogList: any[] = [];

  // 自定义日志转换函数
  const entity2Log = (entity: any, log: any) => {
    return {
      id: entity.m_id?.toString() || entity.entity_id,
      time: log.time || new Date().toISOString(),
      content: log.content || "状态更新",
      type: log.type || "信息"
    };
  };

  // 遍历实体，提取日志
  step.obj_list && step.obj_list.forEach((entity: any) => {
    const entity_id = entity.m_id?.toString() || entity.entity_id;
    const alliance = entity.m_Side === 1 ? "Red" : (entity.alliance || "Blue");
    const logs = entity.logs || [];

    // 为每个实体创建一个状态更新日志
    const statusLog = {
      time: new Date().toISOString(),
      content: `${entity.m_EntityName || entity.entity_name} 位置更新`,
      type: "状态"
    };

    if (alliance === "Blue") {
      blueLogList.push(entity2Log(entity, statusLog));
    } else {
      redLogList.push(entity2Log(entity, statusLog));
    }

    if (logs.length > 0) {
      logs.forEach((log: any) => {
        if (alliance === "Blue") {
          blueLogList.push(entity2Log(entity, log));
        } else {
          redLogList.push(entity2Log(entity, log));
        }
      });
    }
  });

  // 更新日志到store
  if (redLogList.length > 0) {
    simulStoreTuiyan.entityLog.red = [
      ...simulStoreTuiyan.entityLog.red,
      ...redLogList
    ];
  }

  if (blueLogList.length > 0) {
    simulStoreTuiyan.entityLog.blue = [
      ...simulStoreTuiyan.entityLog.blue,
      ...blueLogList
    ];
  }
};

// 判断推演数据动画和静态展示
const animationStatic = async (data: any) => {
  // 使用实时数据
  const success = simulStoreTuiyan.loadLocalData(data);
  if (success) {
    processEntityData(data);
    updateVisualization(data);
  }
};

// 加载推演数据
const loadDeductionData = async () => {
  try {
    const params = {
      task_id: route.query.id as string,
      round_number: props.selectValue,
      start_time: props.taskStatus === 1 ? 0 : undefined
    }
    console.log('加载数据参数:', params);
    const response = await getSituationData(params) as any;

    const data = response.data;
    console.log('获取到的数据:', data);

    // 使用我们添加的新方法加载数据
    const success = simulStoreTuiyan.loadLocalData(data);

    if (success) {
      // 设置总步骤数和初始状态
      state.totalSteps = simulStoreTuiyan.steps.length;
      state.currentStepIndex = 0;
      updateProgress();

      // 确保轨迹显示已开启
      simulStoreTuiyan.isShowPath = true;

      return true;
    } else {
      console.error('数据加载失败');
      return false;
    }
  } catch (error) {
    console.error('加载推演数据失败:', error);
    return false;
  }
};

// 组件挂载成功后
onMounted(async () => {
  try {
    // 确保轨迹显示开启
    simulStoreTuiyan.isShowPath = true;
  } catch (error) {
    console.error('组件挂载时出错:', error);
  }
});

// 处理 viewer 就绪事件
const handleViewerReady = async (viewer: any) => {
  if (!viewer) {
    console.error('Viewer 实例无效');
    return;
  }

  try {
    // 确保 viewer 完全就绪
    await new Promise(resolve => setTimeout(resolve, 500));

    state.customViewerTuiyan = viewer;

    // 初始化轨迹管理器
    if (!simulStoreTuiyan.routesManager) {
      const baseManager = createRoutesManagerTuiyan();
      const extendedManager = baseManager as any;

      extendedManager.addPathPoint = function (entityId: string, cartesian: Cesium.Cartesian3): void {
        if (!this.entityRoutes) this.entityRoutes = {};
        if (!this.entityRoutes[entityId]) {
          this.entityRoutes[entityId] = [];
        }

        try {
          const cartographic = Cesium.Cartographic.fromCartesian(cartesian);
          const longitude = Cesium.Math.toDegrees(cartographic.longitude);
          const latitude = Cesium.Math.toDegrees(cartographic.latitude);

          if (isNaN(longitude) || isNaN(latitude)) {
            return;
          }

          this.entityRoutes[entityId].push(longitude, latitude);

          if (this.entityRoutes[entityId].length >= 4) {
            for (let i = 0; i < this.entityRoutes[entityId].length; i++) {
              if (typeof this.entityRoutes[entityId][i] !== 'number' || isNaN(this.entityRoutes[entityId][i])) {
                return;
              }
            }
            this.refreshRoutes();
          }
        } catch (error) {
          console.error('处理路径点时出错:', error);
        }
      };

      extendedManager.addPoint = extendedManager.addPathPoint;
      extendedManager.addPath = extendedManager.addPathPoint;

      extendedManager.refreshRoutes = function (): void {
        if (!this.datasource) {
          return;
        }
        try {
          cleanAllEntityRoutes(this);
          refreshAllEntityRoutes(this);
        } catch (error) {
          console.error('刷新路径时出错:', error);
        }
      };

      simulStoreTuiyan.routesManager = extendedManager;
    }

    // 使用store中的方法初始化实体列表
    if (simulStoreTuiyan.steps?.length) {
      try {
        simulStoreTuiyan.initializeEntityList(simulStoreTuiyan.steps);
      } catch (error) {
        console.error('初始化实体列表失败:', error);
      }
    }

    // 应用第一步数据
    try {
      await applyStepData(0);
    } catch (error) {
      console.error('应用初始数据失败:', error);
    }
  } catch (error) {
    console.error('处理 viewer-ready 事件时出错:', error);
  }
};

// 组件激活时（从缓存中恢复）
onActivated(async () => {
  try {
    await loadDeductionData();
    simulStoreTuiyan.isShowPath = true;
  } catch (error) {
    console.error('加载推演数据失败:', error);
  }
});

watch(() => props.selectValue, async (newVal) => {
  if (newVal) {
    simulStoreTuiyan.reAllStepsList();

    // 如果任务正在运行
    if (props.taskStatus === 1) {
      // 等待MQ消息通过animationStatic更新数据
      console.log('任务正在运行，等待MQ消息更新');
    }
    // 如果任务未运行
    else if (props.taskStatus === 0) {
      // 确保轨迹显示开启
      simulStoreTuiyan.isShowPath = true;
    }
    // 如果任务运行过(暂停或结束)
    else {
      // 加载该局的历史数据
      const success = await loadDeductionData();
      if (success) {
        simulStoreTuiyan.isShowPath = true;
        // 确保数据加载后处理观察数据
        if (state.customViewerTuiyan) {
          await simulStoreTuiyan.processObservationData(0);
          // 应用第一步数据
          await applyStepData(0);
        }
      }
    }
  }
}, { immediate: true });
// 组件销毁
onBeforeUnmount(() => {
  try {
    if (rmqTimer) {
      clearInterval(rmqTimer);
      rmqTimer = undefined;
    }
    if (simulStoreTuiyan.clientId) {
      customStomp.removeClient(simulStoreTuiyan.clientId);
      simulStoreTuiyan.setIsPause(true);
    }
  } catch (error) {
    console.error('组件销毁时出错:', error);
  }
});

// 暴露给模板使用的变量和方法
defineExpose({
  panelStore,
  ...toRefs(state),
  togglePlayState,
  togglePlay,
  nextStep,
  previousStep,
  animationStatic
});

// 重启仿真
const restartSimulation = async () => {
  // 清除定时器
  if (rmqTimer) {
    clearInterval(rmqTimer);
    rmqTimer = undefined;
  }

  // 重置状态
  state.currentStepIndex = 0;
  state.isPlaying = false;
  updateProgress();

  // 重新加载数据
  await loadDeductionData();

  // 应用第一步数据
  await applyStepData(0);

  // 关闭加载提示
  const app = appStateTuiyan();
  app.spinning = false;
};

// 调整播放速度
const adjustPlaySpeed = (speed: number) => {
  state.playSpeed = speed;

  // 如果正在播放，重启定时器使用新速度
  if (state.isPlaying) {
    pausePlayback();
    startPlayback();
  }
};

// 处理视角变化
const handlePerspectiveChange = async (perspective: string) => {
  // 更新store中的视角设置
  simulStoreTuiyan.currentPerspective = perspective;

  // 确保切换前清理所有路径数据
  if (simulStoreTuiyan.routesManager) {
    cleanAllEntityRoutes(simulStoreTuiyan.routesManager);
  }

  // 使用processObservationData处理当前步骤的数据
  await simulStoreTuiyan.processObservationData(state.currentStepIndex);

  // 重新应用当前步骤数据
  const stepData = simulStoreTuiyan.applyStepData(state.currentStepIndex);

  if (stepData) {
    // 处理实体数据并刷新路径
    processEntityData(stepData);

    // 确保切换后再次清理和刷新所有路径
    if (simulStoreTuiyan.routesManager) {
      refreshAllEntityRoutes(simulStoreTuiyan.routesManager);
    }
  }

  // 请求重新渲染
  if (state.customViewerTuiyan?.scene) {
    try {
      state.customViewerTuiyan.scene.requestRender();
    } catch (e) {
      console.error("视图渲染失败:", e);
    }
  }
};
</script>
<style lang="less">
@import "@@/assets/styles/submodule2.less";

.sub-main {
  position: relative;
}
</style>
